home *** CD-ROM | disk | FTP | other *** search
/ Adobe Graphics & Publishing SDK 1996 December / Adobe Graphics & Publishing SDK 1996 December.iso / mac / After Effects 3.1 SDK Mac / Examples / Effects Samples / Gamma (No Table) / GammaNoTable.c < prev   
Text File  |  1996-11-06  |  10KB  |  338 lines

  1. /**
  2.     GammaNoTable.c
  3.     
  4.     Part of the Adobe After Effects 3.1 SDK.    
  5.     Copyright (c)1993-96, Adobe Systems Inc, All Rights Reserved.
  6.  
  7.     This effect does a simple gamma correction of the image pixels.
  8.     It converts each pixel to a double, applies the gamma power,
  9.     and then converts back to 0-255.  Needless to say, this is
  10.     quite slow.  See the GammaWithTable.c file for a different
  11.     version of the effect that is a bit faster...
  12.  
  13.     This demonstrates:
  14.         iterating over the image pixels (w/o using the Iterate callback)
  15.         calling the progress callback
  16.         requiring an FPU to operate
  17.         a Fixed Slider control
  18.         using the Extent Hint rectangle (from the InData structure)
  19.             this actually has some interesting complications,
  20.             see the Render routine below for explanation...
  21.  
  22.     Revision History
  23.         1.0, created by rb, 12 March 93
  24.         1.1, updated for AE 2.0, dmw, 11 Jan 94
  25.         1.2, updated for Mac/Power Mac dmw, 13 Oct 94
  26.              also fixed bug in iterating over input extent (whoops!)             
  27.         2.0, updated for AE 3.0
  28.         2.1, Added call to AEFX_CLR_STRUCT macro to clear out PF_ParamDef, ba, 6 Nov 96
  29. **/
  30.  
  31. #include "AE_EffectCB.h"
  32. #include "AE_Macros.h"
  33. #include <A4Stuff.h>
  34.  
  35. #define    MAJOR_VERSION        2
  36. #define    MINOR_VERSION        0
  37. #define    BUG_VERSION            0
  38. #define    STAGE_VERSION        PF_Stage_RELEASE
  39. #define    BUILD_VERSION        0
  40.  
  41. #define    NAME    "Gamma (No Table)"
  42.  
  43.  
  44. /** Parameter Definition Constants
  45.  
  46.     Here we define the parameters, their default
  47.     settings, and minimum and maximum values.
  48.  
  49. **/
  50.  
  51. enum {
  52.     GAMMA_INPUT = 0,    /* params index of default input layer */
  53.     GAMMA_GAMMA,        /* params index of gamma correction factor */
  54.  
  55.     GAMMA_NUM_PARAMS
  56. };
  57.  
  58.  
  59. /* We'll allow the gamma correction factor slider vary
  60.  * from 0.1 to 5.0, with the default being at 1.0...
  61.  * If the user brings up the direct number entry dialog,
  62.  * we'll let them type in a value up to 10.0, even though
  63.  * the slider values will stop at 5.0...
  64.  * All of these numbers are in Fixed point.
  65.  */
  66.  
  67. #define    GAMMA_MIN        6554            /* approx 0.1 in fixed point */
  68. #define    GAMMA_MAX        (5L << 16)
  69. #define    GAMMA_BIG_MAX    (10L << 16)
  70. #define    GAMMA_DFLT        (1L << 16)
  71.  
  72.  
  73. /** Command Specific Subroutines
  74.  
  75.     This plug-in only deals with the commands:
  76.         PF_Cmd_ABOUT
  77.         PF_Cmd_GLOBAL_SETUP
  78.         PF_Cmd_GLOBAL_SETDOWN
  79.         PF_Cmd_PARAMS_SETUP
  80.         PF_Cmd_RENDER
  81.     All other commands are ignored.  There is a routine for
  82.     each command, and a main routine to dispatch at the bottom.
  83.  
  84. **/
  85.  
  86. #define DESCRIPTION    "Perform simple (slow) image gamma correction."
  87.  
  88. static PF_Err About (
  89.     PF_InData        *in_data,
  90.     PF_OutData        *out_data,
  91.     PF_ParamDef        *params[],
  92.     PF_LayerDef        *output )
  93. {
  94.     PF_SPRINTF(out_data->return_msg, "%s, v%d.%d\r%s",
  95.         NAME, MAJOR_VERSION, MINOR_VERSION, DESCRIPTION);
  96.  
  97.     return PF_Err_NONE;
  98. }
  99.  
  100.  
  101. static PF_Err GlobalSetup (
  102.     PF_InData        *in_data,
  103.     PF_OutData        *out_data,
  104.     PF_ParamDef        *params[],
  105.     PF_LayerDef        *output )
  106. {
  107.     PF_Err    err = PF_Err_NONE;
  108.  
  109.     /* Need to let AE know what version of the "Basic Gamma" plug-in
  110.      * we are......
  111.      */
  112.      
  113.     out_data->my_version = PF_VERSION(MAJOR_VERSION, MINOR_VERSION,
  114.                                     BUG_VERSION, STAGE_VERSION, BUILD_VERSION);
  115.  
  116.     /* We are only going to iterate over the visible pixels,
  117.      * i.e. the extent_hint rect, so we need to specify the
  118.      * output extent flags. No flag is necessary to use the input extent
  119.      *
  120.      *
  121.      * Each result pixel in the output buffer depends only on the value of
  122.      * the corresponding input pixel, so I'll also set the PIX_INDEPENDENT OutFlag,
  123.      * which can speed up the rendering of field-rendered animations tremendously.
  124.      * Be careful when setting this flag, though; if you set it when it's not true,
  125.      * field rendered output can be quite wrong.
  126.      */
  127.      
  128.     out_data->out_flags |=
  129.         PF_OutFlag_PIX_INDEPENDENT |
  130.         PF_OutFlag_USE_OUTPUT_EXTENT;
  131.  
  132.     return err;
  133. }
  134.  
  135.  
  136. static PF_Err GlobalSetdown (
  137.     PF_InData        *in_data,
  138.     PF_OutData        *out_data,
  139.     PF_ParamDef        *params[],
  140.     PF_LayerDef        *output )
  141. {
  142.     /* We haven't actually allocated any global data,
  143.      * so we don't need to do anything here...
  144.      */
  145.     return PF_Err_NONE;
  146. }
  147.  
  148.  
  149. static PF_Err ParamsSetup (
  150.     PF_InData        *in_data,
  151.     PF_OutData        *out_data,
  152.     PF_ParamDef        *params[],
  153.     PF_LayerDef        *output )
  154. {
  155.     PF_Err            err = PF_Err_NONE;
  156.     PF_ParamDef        def;    /* scratch space for a parameter definition */
  157.  
  158.     /* Always clear out the PF_ParamDef structure before adding your parameters,
  159.      * this macro will do that.
  160.      */
  161.     AEFX_CLR_STRUCT(def);
  162.     
  163.     /* Create the FIXED SLIDER parameter... */
  164.  
  165.     def.param_type = PF_Param_FIX_SLIDER;
  166.     PF_STRCPY(def.name, "Gamma");
  167.     
  168.     /* NOTE: we must set these strings to empty strings to prevent
  169.      * garbage text from being displayed above our sliders... */
  170.      
  171.     def.u.fd.value_str[0] = def.u.fd.value_desc[0] = '\0';
  172.     def.u.fd.value = def.u.fd.dephault = GAMMA_DFLT;
  173.     
  174.     /* The min value of the slider and the min value the user
  175.      * can type in will both be the same value... */
  176.      
  177.     def.u.fd.valid_min = def.u.fd.slider_min = GAMMA_MIN;
  178.     
  179.     /* The max value of the slider will be smaller than the
  180.      * max value the user can type in.  This way, the slider
  181.      * has a nice feel to it, but the user who really wants
  182.      * strange results can access larger values... */
  183.      
  184.     def.u.fd.slider_max = GAMMA_MAX;
  185.     def.u.fd.valid_max = GAMMA_BIG_MAX;
  186.     
  187.     /* Let's let the user see 1 decimal place of precision. */
  188.     
  189.     def.u.fd.precision = 1;
  190.     def.u.fd.display_flags = 0;
  191.  
  192.     if (err = PF_ADD_PARAM(in_data, -1, &def)) return err;
  193.  
  194.     /* Set number of parameters before leaving */
  195.  
  196.     out_data->num_params = GAMMA_NUM_PARAMS;
  197.  
  198.     return err;
  199. }
  200.  
  201.  
  202. /* Render
  203.  *        To render our image, we will iterate over all the pixels,
  204.  *        leaving the alpha untouched, and converting the RGB values
  205.  *        into floating point, then applying the gamma correction
  206.  *        to the values and converting them back again.  We require
  207.  *        an FPU.  You will note that 68881 code generation has been
  208.  *        turned on in the THINK C code generation options. */
  209.  
  210. static PF_Err Render ( 
  211.     PF_InData        *in_data,
  212.     PF_OutData        *out_data,
  213.     PF_ParamDef        *params[],
  214.     PF_LayerDef        *output )
  215. {
  216.     PF_Err            err = PF_Err_NONE;
  217.     long            x, y, w, h, row_gutter_s, row_gutter_d;
  218.     PF_Pixel        *in, *out;
  219.     double            temp, gamma;
  220.  
  221.     /* If the gamma factor is exactly 1.0 just make a direct copy and return now... */
  222.     
  223.     if (params[GAMMA_GAMMA]->u.fd.value == (1L << 16)) {
  224.         err =  PF_COPY(¶ms[0]->u.ld, output, NULL, NULL);
  225.     } else {
  226.     
  227.         /* We are only going to gamma correct the pixels in the
  228.          * in_data extent_hint rectangle.  But there may be pixels
  229.          * in the output extent that are not covered by the in_data
  230.          * extent.  In that case, we need to clear those pixels to
  231.          * zero alpha.  Here, we check if there are pixels in the
  232.          * output outside of the range we will set, and clear them
  233.          * if we have to.  (Just for fun, you can try commenting
  234.          * out this part and seeing what happens... Try masking the
  235.          * image.)
  236.          */
  237.          
  238.         if (in_data->extent_hint.left != output->extent_hint.left ||
  239.             in_data->extent_hint.top != output->extent_hint.top ||
  240.             in_data->extent_hint.right != output->extent_hint.right ||
  241.             in_data->extent_hint.bottom != output->extent_hint.bottom) {
  242.     
  243.             err = PF_FILL(NULL, &output->extent_hint, output);
  244.         }
  245.         
  246.         if (!err) {
  247.             gamma = (double)params[GAMMA_GAMMA]->u.fd.value / (double)(1L << 16);
  248.             gamma = 1.0 / gamma;        /* exponent value is reciprocal of gamma */
  249.  
  250.             x = in_data->extent_hint.left;
  251.             y = in_data->extent_hint.top;
  252.             w = in_data->extent_hint.right - x;
  253.             h = in_data->extent_hint.bottom - y;
  254.         
  255.             in = (PF_Pixel *)((char *)(params[GAMMA_INPUT]->u.ld.data + x) +
  256.                               (y * params[GAMMA_INPUT]->u.ld.rowbytes));
  257.         
  258.             out = (PF_Pixel *)((char *)(output->data + x) + (y * output->rowbytes));
  259.         
  260.             /* NOTE: do not make the assumption here that the input and output
  261.              * buffers have the same rowbytes.  In After Effects 1.0, that
  262.              * was true, but it is not safe in general.
  263.              */
  264.              
  265.             row_gutter_d = output->rowbytes - ((long)w * sizeof(PF_Pixel));
  266.             row_gutter_s = params[GAMMA_INPUT]->u.ld.rowbytes - ((long)w * sizeof(PF_Pixel));
  267.         
  268.             for (; y < h; y++) {
  269.                 for (x = 0; x < w; x++) {
  270.                     out->alpha = in->alpha;
  271.         
  272.                     temp = (double)in->red / 255.0;
  273.                     temp = PF_POW(temp, gamma);
  274.                     out->red = (unsigned char)(temp * 255.0);
  275.         
  276.                     temp = (double)in->green / 255.0;
  277.                     temp = PF_POW(temp, gamma);
  278.                     out->green = (unsigned char)(temp * 255.0);
  279.         
  280.                     temp = (double)in->blue / 255.0;
  281.                     temp = PF_POW(temp, gamma);
  282.                     out->blue = (unsigned char)(temp * 255.0);
  283.         
  284.                     /* move to the next pixel */
  285.                     
  286.                     in++;
  287.                     out++;
  288.                 }
  289.         
  290.                 /* move to the start of the next row */
  291.                 
  292.                 in = (PF_Pixel *)((char *)in + row_gutter_s);
  293.                 out = (PF_Pixel *)((char *)out + row_gutter_d);
  294.         
  295.                 /* update the progress bar -- we're about to start line y+1 */
  296.                 
  297.                 if (err = PF_PROGRESS(in_data, y + 1, h)) break;
  298.             }
  299.         }
  300.     }
  301.     
  302.     return err;
  303. }
  304.  
  305.  
  306. PF_Err main (
  307.     PF_Cmd            cmd,
  308.     PF_InData        *in_data,
  309.     PF_OutData        *out_data,
  310.     PF_ParamDef        *params[],
  311.     PF_LayerDef        *output )
  312. {
  313.     PF_Err        err = PF_Err_NONE;
  314.     EnterCodeResource();        /* only works in Metrowerks */
  315.     
  316.     switch (cmd) {
  317.     case PF_Cmd_ABOUT:
  318.         err = About(in_data,out_data,params,output);
  319.         break;
  320.     case PF_Cmd_GLOBAL_SETUP:
  321.         err = GlobalSetup(in_data,out_data,params,output);
  322.         break;
  323.     case PF_Cmd_PARAMS_SETUP:
  324.         err = ParamsSetup(in_data,out_data,params,output);
  325.         break;
  326.     case PF_Cmd_GLOBAL_SETDOWN:
  327.         err = GlobalSetdown(in_data,out_data,params,output);
  328.         break;
  329.     case PF_Cmd_RENDER:
  330.         err = Render(in_data,out_data,params,output);
  331.         break;
  332.     }
  333.  
  334.     ExitCodeResource();        /* only works in Metrowerks */
  335.  
  336.     return err;
  337. }
  338.